2.5 主要代码片段及说明
首先是可调频率和占空比的PWM波,经过一阶低通滤波器后接入高速比较器负输入端。
always @(posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n == 1'b0)
cnt <= 8'b0;
else if(cnt == 8'b1111)
cnt <= 8'b0;
else
cnt = cnt + 1'b1;
end
always @(posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n == 1'b0)
pwm_out <= 1'b0;
else if(cnt <= 8'd10)
pwm_out <= 1'b1;
else
pwm_out <= 1'b0;
end
然后是频率测量模块。
always @(posedge clk_test or negedge sys_rst_n) begin
if(sys_rst_n == 1'b0)
freq_cnt <= 26'b0;
else
freq_cnt <= freq_cnt + 1'b1;
end
always @(posedge clk_1s or negedge clk_1s or negedge sys_rst_n) begin
if(sys_rst_n == 1'b0)
freq <= 26'b0;
else begin
if(freq_cnt >= freq_cnt_buff) freq = freq_cnt - freq_cnt_buff;
freq_cnt_buff = freq_cnt;
end
end
按键控制模式变换,同时被测信号频率大于1M时改显示单 位,变为kHz。
//控制模式翻转
reg h_or_l_r;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
h_or_l_r <= 1'b0;
else
begin
if(key_out == 1'b1) h_or_l_r <= ~h_or_l_r;
end
end
assign h_or_l = h_or_l_r;
//检测到按键输入,切换模式
always @(posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n == 1'b0)
date_buff <= 1'b0;
else if(freq_or_count == 1'b0)
date_buff <= count_buff - 1'b1;
else if(freq_or_count == 1'b1 && freq_buff < 20'd1000000)
date_buff <= freq_buff;
else
date_buff <= freq_buff_div;
end
assign led_R = (freq_or_count == 1'b1) ? 8'b11110000 : 8'b00001111;
这里的计数器同样套用了按键消抖模块。
//计数加一
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
count <= 1'b0;
else
if((key_out == 1'b1) && (freq_or_count == 1'b0)) count = count + 1'b1;
end
以上两个主要功能模块获取到频率和计数数据后,转换成BCD码的形式,方便OLED显示。
//当计数器等于20时,移位判断操作完成,对各个位数的BCD码进行赋值
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
begin
unit <= 4'b0;
ten <= 4'b0;
hun <= 4'b0;
tho <= 4'b0;
t_tho <= 4'b0;
h_hun <= 4'b0;
end
else if(cnt_shift == 5'd21)
begin
unit <= data_shift[23:20];
ten <= data_shift[27:24];
hun <= data_shift[31:28];
tho <= data_shift[35:32];
t_tho <= data_shift[39:36];
h_hun <= data_shift[43:40];
end
将OLED屏幕划分为4行,每行显示16个字符,在第一行显示模式(frequency/counter),第三行显示数值。第四行当单位为kHz时,显示余下的个十百位。
5'd0: begin state <= INIT; end
5'd1: begin if(freq_or_count == 1'b1) begin
y_p <= 8'hb0; x_ph <= 8'h10; x_pl <= 8'h00; num <= 5'd16; char <= " frequency ";state <= SCAN; end
else begin
y_p <= 8'hb0; x_ph <= 8'h10; x_pl <= 8'h00; num <= 5'd16; char <= " counter ";state <= SCAN; end
end
5'd2: begin y_p <= 8'hb1; x_ph <= 8'h10; x_pl <= 8'h00; num <= 5'd16; char <= " ";state <= SCAN; end
5'd3: begin y_p <= 8'hb2; x_ph <= 8'h10; x_pl <= 8'h00; num <= 5'd16; char <= str_out ;state <= SCAN; end
5'd4: begin y_p <= 8'hb3; x_ph <= 8'h10; x_pl <= 8'h00; num <= 5'd16; char <= str_out_1 ;state <= SCAN; end